import numpy as np
import pandas as pd
from rdkit import DataStructs
from rdkit.Chem import AllChem
from sklearn.model_selection import GridSearchCV
from sklearn.neural_network import MLPClassifier

dfc_train = pd.read_excel("reaction_class_model0606.xlsx")
dfc_test = pd.read_excel("reaction_class_model_test622.xlsx")

ls = []
for i in range(len(dfc_train)):
    S = dfc_train['substrate_smiles_canonical'][i]
    try:
        m = AllChem.MolFromSmiles(S)
        fps = AllChem.GetMorganFingerprintAsBitVect(m, 3, nBits=2048)
        array = np.zeros((0,), dtype=np.float64)
        DataStructs.ConvertToNumpyArray(fps, array)
        ls.append(array)
    except (Exception,):
        print(dfc_train['substrate_name'][i])
X_train = np.array(ls)

# transform reaction class to array for model
y_train = dfc_train.iloc[:, 3:23].to_numpy(dtype=np.float64)
X_train = X_train.astype(float)
y_train = y_train.astype(float)

# ls2 = []
# for i in range(len(dfc_test)):
#     S = dfc_test['substrate_smiles_canonical'][i]
#     try:
#         m = AllChem.MolFromSmiles(S)
#         fps = AllChem.GetMorganFingerprintAsBitVect(m, 3, nBits=2048)
#         array = np.zeros((0,), dtype=np.float64)
#         DataStructs.ConvertToNumpyArray(fps, array)
#         ls2.append(array)
#     except (Exception,):
#         print(dfc_test['substrate_name'][i])
#
# X_test = np.array(ls2)
# # transform reaction class to array for model
# y_test = dfc_test.iloc[:, 4:24].to_numpy(dtype=np.float64)
# X_test = X_test.astype(float)
# y_test = y_test.astype(float)

mlpc_params = {"alpha": [0.0001,0.00001],
               "learning_rate_init": [0.001,0.00001],
               "hidden_layer_sizes": [(100,), (2048,),(2048, 100)],
               "solver": ["adam"],
               "activation": ["relu", "logistic"],
               }
mlpc = MLPClassifier(random_state=0)  # ANN model object created

# Model CV process
mlpc_cv_model = GridSearchCV(mlpc, mlpc_params,
                             cv=5,  # To make a 5-fold CV
                             n_jobs=-1,  # Number of jobs to be run in parallel (-1: means to use all processors)
                             verbose=2)  # Controls the level of detail: higher means more messages gets value as integer.

mlpc_cv_model.fit(X_train, y_train)

# The best parameter obtained as a result of CV process

print("The best parameters: " + str(mlpc_cv_model.best_params_))
